
#ifndef _REF_PTR_
#define _REF_PTR_

#include "TemplateImpl/RefPtrImpl.h"

namespace nebula { namespace utility {

template<typename T, typename ThreadPolicy = single_thread>
class ref_ptr
{
private:
	typedef ref_ptr<T, ThreadPolicy> this_type;

public:
	typedef T   element_type;
	typedef T   value_type;
	typedef T * pointer;
	typedef T & reference;

	explicit ref_ptr(): _px(0), _pn()
	{
	}

	template<typename Y>
	ref_ptr( Y * p ): _px( p ), _pn( p )
	{
	}

	template<typename Y, typename D>
	ref_ptr( Y * p, D d): _px( p ), _pn( p, d )
	{
	}

	explicit ref_ptr(ref_ptr<T, ThreadPolicy> &other)
	{
		_px = other._px;
		_pn = other._pn;
	}

	T* get() const
	{
		return _px;
	}

	reference operator*() const
	{
		return *_px;
	}

	pointer operator->() const
	{
		return _px;
	}

	template<class Y>
	ref_ptr(ref_ptr<Y, ThreadPolicy> const & r): _px(r._px), _pn(r._pn)
	{
	}

	this_type& operator=(this_type const &other)
	{
		_px = other._px;
		_pn = other._pn;
		return *this;
	}

	long use_count() const
	{
		return _pn.use_count();
	}

	void swap(this_type &other)
	{
		std::swap(_px, other._px);
		_pn.swap(other._pn);
	}

	void reset()
	{
		this_type().swap(*this);
	}

	template<class Y> void reset(Y * p)
	{
		this_type(p).swap(*this);
	}

private:
	T * _px;
	refptr_count<ThreadPolicy> _pn;
};

template<class T, class U> inline bool operator==(ref_ptr<T> const & a, ref_ptr<U> const & b)
{
	return a.get() == b.get();
}

template<class T, class U> inline bool operator!=(ref_ptr<T> const & a, ref_ptr<U> const & b)
{
	return a.get() != b.get();
}

template<class T, class U> inline bool operator<(ref_ptr<T> const & a, ref_ptr<U> const & b)
{
	return a.get() < b.get();
}

}} // namespace nebula::utility

#endif
